package com.niiwoo.civet.user.service.duboo;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.trade.enums.TradeConfigEnum;
import com.niiwoo.civet.trade.service.configure.TradeConfigDubboService;
import com.niiwoo.civet.user.constants.LoginAccountErrorCode;
import com.niiwoo.civet.user.dao.entity.*;
import com.niiwoo.civet.user.dto.request.SMSChangeMobileNoRequestDTO;
import com.niiwoo.civet.user.dto.request.UpdateUserBasicInfIMRequestDTO;
import com.niiwoo.civet.user.enums.MobileChangeRecordEnum;
import com.niiwoo.civet.user.enums.UserDataStatusEnum;
import com.niiwoo.civet.user.enums.UserDataTypeEnum;
import com.niiwoo.civet.user.enums.UserSMSTypeEnum;
import com.niiwoo.civet.user.service.ImDubboService;
import com.niiwoo.civet.user.service.MobileChangeRecordDubboService;
import com.niiwoo.civet.user.service.dataflow.UserProfessionInfoBackFlowDubboService;
import com.niiwoo.civet.user.service.local.MobileChangeRecordService;
import com.niiwoo.civet.user.service.local.UserLoginAccountService;
import com.niiwoo.civet.user.service.local.UserStatusService;
import com.niiwoo.civet.user.service.local.sms.SMSSenders;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.im.component.IMService;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Service(version = "1.0.0")
public class MobileChangeRecordDubboServiceImpl implements MobileChangeRecordDubboService {

    @Autowired
    IMService imService;
    @Autowired
    SMSSenders smsSender;
    @Autowired
    PrivacyMasks privacyMasks;
    @Autowired
    SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    MobileChangeRecordService mobileChangeRecordService;
    @Autowired
    UserLoginAccountService userLoginAccountLocalService;
    @Autowired
    UserStatusService userStatusService;

    @Reference(version = "1.0.0")
    private ImDubboService imDubboService;
    @Reference(version = "1.0.0")
    private TradeConfigDubboService tradeConfigDubboService;
    @Reference(version = "1.0.0")
    private UserProfessionInfoBackFlowDubboService userProfessionInfoBackFlowDubboService;

    @Override
    public void smsChangeMobileNo(SMSChangeMobileNoRequestDTO requestDTO) {
        // 验证码
        if (!smsSender.isAuthCodeCacheRight(UserSMSTypeEnum.OLD_CHANGE_MOBILE_NO, privacyMasks.decryptPrivacy(requestDTO.getMobileNo()), requestDTO.getSmsCode())) {
            throw new BizException(LoginAccountErrorCode.SMS_CODE_ERROR);
        }
        // 查找用户映射
        LoginAccountMapping loginAccountMapping = userLoginAccountLocalService.getAccountMapping(requestDTO.getMobileNo());
        if (loginAccountMapping == null) {
            throw new BizException(LoginAccountErrorCode.USERS_NOT_EXIST);
        }
        // 查找用户账号
        UcAccount ucAccount = userLoginAccountLocalService.getAccountByUserId(loginAccountMapping.getUserId());
        if (ucAccount == null) {
            throw new BizException(LoginAccountErrorCode.USERS_NOT_EXIST);
        }

    }

    @Override
    public void smsConfirmationMobileNo(SMSChangeMobileNoRequestDTO requestDTO) {
        // 查找用户映射
        LoginAccountMapping loginAccountMapping = userLoginAccountLocalService.getAccountMapping(requestDTO.getMobileNo());
        if (loginAccountMapping != null) {
            throw new BizException("USR10034");
        }
        // 新旧手机号比对
        UcAccount ucAccount = userLoginAccountLocalService.getAccountByUserId(requestDTO.getUserId());
        if (ucAccount.getMobileNo().equals(requestDTO.getMobileNo())) {
            throw new BizException("USR10033");
        }
        // 验证码
        if (!smsSender.isAuthCodeCacheRight(UserSMSTypeEnum.NEW_CHANGE_MOBILE_NO, privacyMasks.decryptPrivacy(requestDTO.getMobileNo()), requestDTO.getSmsCode())) {
            throw new BizException(LoginAccountErrorCode.SMS_CODE_ERROR);
        }

        // 更新用户映射表
        LoginAccountMapping accountMapping = new LoginAccountMapping();
        accountMapping.setUserId(requestDTO.getUserId());
        accountMapping.setAccountName(requestDTO.getMobileNo());

        // 更新用户账号表
        UcAccount account = new UcAccount();
        account.setUserId(requestDTO.getUserId());
        account.setMobileNo(requestDTO.getMobileNo());

        // 更新用户基础表
        UserBasicInfo userBasicInfo = new UserBasicInfo();
        userBasicInfo.setUserId(requestDTO.getUserId());
        userBasicInfo.setMobileNo(requestDTO.getMobileNo());

        // 插入手机号变更记录
        MobileChangeRecord mobileChangeRecord = new MobileChangeRecord();
        mobileChangeRecord.setId(snowflakeIdWorker.nextId());
        mobileChangeRecord.setUserId(requestDTO.getUserId());
        mobileChangeRecord.setMobileNo(ucAccount.getMobileNo());
        mobileChangeRecord.setChangeType(requestDTO.getType());
        mobileChangeRecord.setChangeDate(new Date());
        mobileChangeRecord.setUpdateTime(new Date());
        mobileChangeRecord.setCreateTime(new Date());

        // 修改运营商状态
        DataStatus dataStatus = new DataStatus();
        dataStatus.setUserId(requestDTO.getUserId());
        dataStatus.setDataType(UserDataTypeEnum.OPERATOR_AUTHORIZE.getValue());
        dataStatus.setDataStatus(UserDataStatusEnum.PhoneOperatorStatus.NOCREDIT.getStatus());
        dataStatus.setAuthTime(new Date());

        boolean result = mobileChangeRecordService.smsChangeMobileNo(accountMapping, account, userBasicInfo, mobileChangeRecord, dataStatus);
        if (result) {
            // 推送给IM
            UpdateUserBasicInfIMRequestDTO imRequestDTO = new UpdateUserBasicInfIMRequestDTO();
            imRequestDTO.setGuid(requestDTO.getUserId());
            imRequestDTO.setMobile(privacyMasks.decryptPrivacy(requestDTO.getMobileNo()));
            try {
                log.info("MobileChangeRecordDubboServiceImpl.smsChangeMobileNo imRequestDTO={} start", JSON.toJSONString(imRequestDTO));
                imDubboService.updateUserBasicInfIM(imRequestDTO);
            } catch (Exception e) {
                log.error("MobileChangeRecordDubboServiceImpl.smsChangeMobileNo imRequestDTO={}, errorMessage={}", JSON.toJSONString(imRequestDTO), e.getMessage());
            }

            // 天秤回流
            try {
                log.info("MobileChangeRecordDubboServiceImpl.smsConfirmationMobileNo userId={} start", requestDTO.getUserId());
                CompletableFuture.runAsync(() -> userProfessionInfoBackFlowDubboService.changeMobileNo(requestDTO.getUserId()));
            } catch (Exception e) {
                log.error("MobileChangeRecordDubboServiceImpl.smsConfirmationMobileNo userId={} error", requestDTO.getUserId());
            }
        }
    }

    @Override
    public boolean selectMobileChangeRecord(String userId) {
        MobileChangeRecord mobileChangeRecord = mobileChangeRecordService.selectMobileChangeRecord(userId);
        if (mobileChangeRecord == null) {
            return false;
        }

        int limitDays = 90;
        Map<String, String> tradeConfigMap = tradeConfigDubboService.selectTradeConfigByEmuns(Arrays.asList(TradeConfigEnum.CHANGE_MOBILE_LIMIT_TIME));
        if (!CollectionUtils.isEmpty(tradeConfigMap)) {
            limitDays = Integer.parseInt(tradeConfigMap.get(TradeConfigEnum.CHANGE_MOBILE_LIMIT_TIME.getConfigKey()));
        }
        return new DateTime(mobileChangeRecord.getChangeDate()).plusDays(limitDays).isAfterNow();
    }

    @Override
    public Byte selectUserDataStatus(String userId) {
        Byte bindBankCard = Byte.valueOf("0");
        Byte twoElement = Byte.valueOf("0");
        List<DataStatus> dataStatusList = userStatusService.getDataStatusByUserId(userId);
        for (DataStatus dataStatus : dataStatusList) {
            UserDataTypeEnum userDataTypeEnum = UserDataTypeEnum.of(dataStatus.getDataType());
            if (userDataTypeEnum != null) {
                switch (userDataTypeEnum) {
                    case TWO_ELEMENT: twoElement = dataStatus.getDataStatus(); break;
                    case BIND_BANK_CARD: bindBankCard = dataStatus.getDataStatus(); break;
                    default: break;
                }

            } else {
                log.warn("MobileChangeRecordDubboServiceImpl.selectUserDataStatus userId={}, dataStatus={}", userId, dataStatus);
            }
        }
        log.warn("MobileChangeRecordDubboServiceImpl.selectUserDataStatus userId={}, bindBankCard={}, twoElement={}",userId, bindBankCard, twoElement);
        if (UserDataStatusEnum.OpenBankAccountStatus.PASS_BIND.getStatus().equals(bindBankCard)
                && UserDataStatusEnum.RealNameAuthStatus.PASS_CERTIFIED.getStatus().equals(twoElement)) {
            return MobileChangeRecordEnum.ChangePhoneNumberEnum.OPEN_AN_ACCOUNT.getValue();
        }
        if (UserDataStatusEnum.RealNameAuthStatus.PASS_CERTIFIED.getStatus().equals(twoElement)) {
            return MobileChangeRecordEnum.ChangePhoneNumberEnum.PASS_CERTIFIED_NO_ACCOUNT_OPENING.getValue();
        }
        return MobileChangeRecordEnum.ChangePhoneNumberEnum.NOT_REAL_NAME.getValue();
    }

}
